package com.kgc.sbt.service.impl;

import com.kgc.sbt.config.BuyLimitConfig;
import com.kgc.sbt.service.BuyLimitService;
import com.kgc.sbt.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * Created on 2021-06-19.
 * <p>
 * Author: zhukang
 * <p>
 * Description:
 */
@Service
public class BuyLimitServiceImpl implements BuyLimitService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private BuyLimitConfig buyLimitConfig;

    @Override
    public boolean initProdStockToRedis(String prodId) {
        // 从redis获取商品库存数量，如果已经存在，就不需要重复添加
        // 如果redis中没有，需要存入redis
        return redisUtils.get(buyLimitConfig.getStockNumPrefix() + prodId) == null
                && redisUtils.set(buyLimitConfig.getStockNumPrefix() + prodId, buyLimitConfig.getProdStockNum());
    }

    @Override
    public boolean lockBuyUser(String userId, String prodId) {

        // 借助redis的分布式锁，锁定用户，要使用名称空间概念
        return redisUtils.lock(buyLimitConfig.getLockUserPrefix() + prodId + ":" + userId, null, buyLimitConfig.getBuyLimitTime());
    }

    @Override
    public boolean checkProdStock(String prodId, Integer buyCount) {
        // 从redis获取当前商品库存
        Object prodStockNum = redisUtils.get(buyLimitConfig.getStockNumPrefix() + prodId);

        // 如果库存存在且充足，返回true，否则返回false
        return prodStockNum != null && Integer.valueOf(prodStockNum.toString()) >= buyCount;
    }

    @Override
    public boolean isStockLock(String prodId) {

        // 直接进行上锁，（setnx，如果已经锁定，上锁失败），上锁成功，没有用抢购，可以进行后续流程，如果上锁失败，代表有人抢购，等待
        return !redisUtils.lock(buyLimitConfig.getStockLockPrefix() + prodId, null, buyLimitConfig.getStockLockTime());
    }

    @Override
    public void setTradeOrderNo2Redis(String userId, String tradeOrderNo) {
        // redisUtils.set(userId, tradeOrderNo);
        // 方便演示，存订单号作为key，实际上，应该是用户是唯一标识，方便前端根据用户编号判断订单是否生成成功
        redisUtils.set(tradeOrderNo, userId);
    }

    @Override
    public boolean isTradeOrderCreated(String tradeOrderNo) {
        return ObjectUtils.isEmpty(redisUtils.get(tradeOrderNo));
    }

    @Override
    public void subProdStockNum(String prodId, Integer buyCount) {
        redisUtils.decr(buyLimitConfig.getStockNumPrefix() + prodId, buyCount);
    }

    @Override
    public void unlockProdStockLock(String prodId) {
        redisUtils.delLock(buyLimitConfig.getStockLockPrefix() + prodId);
    }
}
